<?php
/**
 * 简单SESSION处理类
 *
 * @filesource _session.class.php
 * @package peck
 * @subpackage _helper
 * @version $id: 0.2, utf8, Thu Feb  4 17:18:32 CST 2010
 * @author LD King <kldscs[at]gmail.com>
 * @copyright Copyleft (D.) 2007 - 2010 MiFunny China Inc.
 * @link http://mifunny.info/
 * @see  
 * 
 *   session_cache_limiter内的几个参数意义是：
 *   	nocache：当然是不缓存（比如：表单信息被清除），但公共变量可以缓存
 *   	private：私有方式缓存（比如：表单信息被保留，但在生存期内有效）
 *   	private_no_cache：私有方式但不过期（表单信息被保留）
 *   	publice：公有方式，（表单信息也被保留）
 *   session_cache_expire函数，缺省是180分钟
 */
class _session{
	/**
	 * SISSION单例
	 * 
	 * @var object _seesion
	 */
	private static $instance;
	
	/**
	 * SESSION 生存时间
	 * 
	 * @var int
	 */
	protected $session_ttl;

	/**
	 * prefix for "flash" variables (eg. flash:new:message)
	 * 
	 * @var string
	 */
	protected $prefix;
	
	/**
	 * cookie 相关
	 *   函数 setcookie
	 */
	protected $cookie = array(
		'expire' => 42000, // The lifetime of the cookie in seconds. (1个月)
		'path' => '/',
		'domain' => null,
		'secure' => false,
		'httponly' => false,
	);

    //当前时间截
    protected $time;

	private function __construct(){}
	private function __clone(){}
	   
	/**
	 * 获得静态对像
	 *
	 * @return object _seesion
	 */
	public static function object(){
	 	//if( !(self::$instance instanceof self) ){
		if(session_id() == ''){   		
            self::$instance = new self();
            self::$instance->time = $time = time();

	   	//	$s = _core::get('session');
	   	    $oo = '__configs'; $key = 'session';            
            $s =& $GLOBALS[$oo][$key];

	   		if( !empty($s['cache_limiter']) ){
	   			session_cache_limiter($s['cache_limiter']);
   				is_numeric($s['cache_expire']) and session_cache_expire($s['cache_expire']);
	   		}
	   		empty($s['save_path']) or session_save_path($s['save_path']);
	   		
	   		if( !is_numeric($s['session_ttl']) ){
	   			$s['session_ttl'] = (int)ini_get('session.gc_maxlifetime');
				 //_core::set('session/session_ttl', $s['session_ttl']);
	   		}
	   		self::$instance->session_ttl = $s['session_ttl'];
	   		
	   		//Set Cookie
	   		if( !empty($s['cookie_lifetime']) ){
	   		    if( is_numeric($s['cookie_lifetime']) ){
                    self::$instance->cookie['expire'] = $time + $s['cookie_lifetime'];
                }else
                   $s['cookie_lifetime'] = self::$instance->cookie['expire'];
                
                if(!empty($s['cookie_domain'])){
                    self::$instance->cookie['domain'] = $s['cookie_domain'];
                }else
                    $s['cookie_domain'] = $_SERVER["HTTP_HOST"];

	   			session_set_cookie_params($s['cookie_lifetime'], '/', $s['cookie_domain']);
	   		}else{
	   			self::$instance->cookie['expire'] = $time + self::$instance->cookie['expire'];
	   		}
	   		
	   		self::$instance->prefix = empty($s['prefix']) ? 'default' : $s['prefix'];
	   		session_start();
	   }
	   
	   if( !self::$instance->_is_expired() ){
	   		self::$instance->regenerate_id();
	   }
	   return self::$instance;
	}//END func object
	

    public function getOption($key){
	   	$oo = '__configs'; $key = 'session';            
        $s =& $GLOBALS[$oo][$key];
        return empty($s[$key]) ? null : $s[$key];
    }

	/**
	 * Destroys the session and erases session storage
	 */
	public function destroy(){
		unset($_SESSION);
		$session_name = session_name();
		if( isset($_COOKIE[$session_name]) ) {
			$expire = time() - $this->getOption('cookie_lifetime');
			setcookie(session_name(), '', $expire, '/', $this->cookie['domain']);
		}
		return session_destroy();
	}
	   
	/**
	 * 设置SESSION值
	 * 
	 * @param string $key
	 * @param mixed $value
	 * @param string $prefix
	 */
	public function set($key, $value=null, $prefix=null){
		$key = $this->_key($key, $prefix);
		if(is_null($value)){
			unset( $_SESSION[$key] );
		}else $_SESSION[$key] = $value;
	}
	
	/**
	 * 获得SESSION值, 不存在 返回 NULL
	 * 
	 * @param string $key
	 * @param string $prefix
	 * 
	 * @return mixed
	 */
	public function get($key, $prefix=null){
		$key = $this->_key($key, $prefix);
		return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
	}
	
	/**
	 * 得到key
	 * 
	 * @param string $key
	 * @param string $prefix
	 */
	private function _key($key, $prefix=null) {
		return is_null($prefix) ? $this->prefix.'::'.$key : $prefix.'::'.$key;
	}
	
	/**
	 * 获取/设置SESSION PREFIX, 用户同一浏览器 多用户登陆的情况
	 * 
	 * @param string $prefix  默认 null, 返回当前prefix; 否则设置 prefix;
	 * 
	 * @return boolean
	 */
	public function prefix($prefix=null){
		if( is_null($prefix) ){
			return $this->prefix;
		}else{
			$this->prefix = $prefix;
		}
	}
	
	/**
	 * SESSION 数值轮转
	 * 
	 * @param string $new_prefix
	 * @param string $old_prefix
	 */
	public function change($new_prefix, $old_prefix=null){
		if(count($_SESSION)>0){
			if( is_null($old_prefix) ){
				$pattern = '/(.+?)(\:\:.+)/';
			}else $pattern = '/('.preg_quote($old_prefix).')(\:\:.+)/';
			$replacement = $new_prefix.'$2';
						
			foreach($_SESSION as $k=>$v){
				$k2 = preg_replace($pattern, $replacement, $k, 1);
				if( $k != $k2 ){
					$_SESSION[$k2] = $_SESSION[$k];
					unset($_SESSION[$k]);
				}
			}//END for
		}
	}//END change
	
	/**
	 * Regenerates session id, 网友 Hex 原生 SEESION
	 */
	public function regenerate_id(){
		// copy old session data, including its id
		$old_session_id = session_id();
		$old_session_data = $_SESSION;
	
		// regenerate session id and store it
		session_regenerate_id();
		$new_session_id = session_id();
	
		// switch to the old session and destroy its storage
		session_id($old_session_id);
		session_destroy();
	
		// switch back to the new session id and send the cookie
		session_id($new_session_id);
		session_start();

		// restore the old session data into the new session
		$_SESSION = $old_session_data;
	
		// update the session creation time
		$_SESSION['regenerated'] = $this->time;
	
		// session_write_close() patch based on this thread
		// http://www.codeigniter.com/forums/viewthread/1624/
		// there is a question mark ?? as to side affects
	
		// end the current session and store session data.
		session_write_close();
	}//END func regenerate_id
	
	/**
	 * Checks if session has expired
     */
	private function _is_expired(){
		empty($_SESSION['regenerated']) and $_SESSION['regenerated'] = $this->time;
		
		if ( time()-$_SESSION['regenerated'] <= $this->session_ttl ){
			return true;
		}

		return false;
	}//END func _is_session_expired
	
	/**
     * 获得 Cookie 数据
     *
     * 从 $_COOKIE 中获得指定参数，如果参数不存在则返回 $default 指定的默认值。
     *   如果 $key 参数为 null，则返回整个 $_COOKIE 的内容。
     *
     * @param string $key 要查询的参数名
     * @param mixed $default 参数不存在时要返回的默认值
     *
     * @return mixed 参数值
     */
    public function get_cookie($key = null, $default = null){
        if (is_null($key))
            return $_COOKIE;
        return isset($_COOKIE[$key]) ? $_COOKIE[$key] : $default;
    }//END func cookie
    
    /**
     * 设置 Cookie 数据
     *   如果 $key 参数为 null，清空 $_COOKIE
     *
     * @param string $key
     * @param mixed $value 
     * @param int expire 持久时间 
     */
    public function set_cookie($key = null, $value = null, $expire=null){
    	if(is_null($key)){
    		unset($_COOKIE);
    	}else{
    		$expire = is_null($expire) ? $this->cookie['expire'] : (time()+$expire);
    		setcookie($key, $value, $expire, '/', $this->cookie['domain']);
    	}
    }//END func cookie
    
}//END class _session

